/**
 * 
 */
package soa.security.mgr.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.naming.Name;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import soa.security.Constants;
import soa.security.domain.Department;
import soa.security.domain.Department.Departments;
import soa.security.domain.Group;
import soa.security.domain.OrganizationUnit;
import soa.security.domain.Person;
import soa.security.domain.Position;
import soa.security.domain.Role;
import soa.security.exception.AdapterException;
import soa.security.exception.OrganizationException;
import soa.security.mgr.service.DepartmentMgrService;
import soa.security.util.BeanUtils;
import soa.security.util.JaxbUtils;

/**
 * @author Cre.Gu
 *
 */
@Service
public class DepartmentMgrServiceImpl extends BaseMgrServiceImpl implements
		DepartmentMgrService {
	protected final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(this.getClass());

	@Override
	public void addDepartment(String organizationId, Department d)
			throws OrganizationException {
		try {
			if (StringUtils.isBlank(d.getBid())) {
				d.setBid("DE" + findMaxNumber(Department.class));
			}
			validate(d);
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);

			d.setRegionCode(findOrganization(organizationId).getRegionCode());

			d.setDn(d.buildDn(unit.getDn()));
			departmentDao.create(d);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	@Override
	public void updateDepartment(String organizationId, Department d)
			throws OrganizationException {
		try {
			validateOrganization(organizationId);
			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);
			validateDepartment(unit.getDn().toString(), d.getBid());

			Department up = departmentDao.findByPrimaryKey(unit.getDn()
					.toString(), d.getBid());
			BeanUtils.copyPropertiesWithoutNull(d, up);
			d = up;

			validate(d);

			d.setDn(d.buildDn(unit.getDn()));
			departmentDao.update(d);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	@Override
	public List<Department> allDepartments(String organizationId)
			throws OrganizationException {
		return allDepartments(organizationId, null, false);
	}

	@Override
	public List<Department> allDepartments(String organizationId,
			Map<String, Object> parameters, boolean subTree)
			throws OrganizationException {
		return departmentAllDepartments(organizationId, parameters, subTree);
	}

	@Override
	public List<Department> allSubDepartments(String organizationId,
			String parentBid) throws OrganizationException {
		return allSubDepartments(organizationId, parentBid, null);
	}

	@Override
	public List<Department> allSubDepartments(String organizationId,
			String parentBid, Map<String, Object> parameters)
			throws OrganizationException {
		List<Department> results = new ArrayList<Department>();
		try {
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);

			results = departmentDao.allSubDepartments(unit.getDn().toString(),
					parentBid, defaultSearchScope, parameters);
			sortResult(results);
		} catch (Exception e) {
			wrapException(e);
		}
		return results;
	}

	@Override
	public List<Department> getDepartment(String organizationId,
			String departmentId) throws OrganizationException {
		List<Department> list = new ArrayList<Department>();
		try {
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);
			validateDepartment(unit.getDn().toString(), departmentId);

			Name dn = LdapNameBuilder.newInstance(unit.getDn())
					.add(Constants.BID, departmentId).build();
			list.add(departmentDao.findByDn(dn.toString()));

		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	private void validate(Department d) {
		Assert.hasText(d.getBid(), "部门编码不能为空");
		Assert.hasText(d.getName(), "部门名称不能为空");

		BeanUtils.blank2Null(d);
	}

	@Override
	public boolean addPersons(String organizationId, String departmentId,
			String personIds) throws OrganizationException {
		return addUnit(organizationId, departmentId, personIds,
				Constants.PERSON);
	}

	@Override
	public boolean removePersons(String organizationId, String departmentId,
			String personIds) throws OrganizationException {
		return removeUnit(organizationId, departmentId, personIds,
				Constants.PERSON);
	}

	@Override
	public List<Person> allPersons(String organizationId, String departmentId)
			throws OrganizationException {
		return departmentAllPersons(organizationId, departmentId, null);
	}
	
	@Override
	public Page<Person> allPersons(String organizationId, String departmentId, PageRequest request)
			throws OrganizationException {
		// TODO Auto-generated method stub
		List<Person> list = new ArrayList<Person>();
		try {
			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId, Constants.DEPARTMENT);
			validateDepartment(deUnit.getDn().toString(), departmentId);

			List<String> pids_page = new ArrayList<String>();
			List<String> pids = departmentDao
					.allPersons(departmentDao.findByPrimaryKey(deUnit.getDn().toString(), departmentId));
			
			int total = pids.size();	//总数
			
			int pageSize = request.getPageSize();	//每页数
			int pageNumber = request.getPageNumber();	//当前页码
			
			int totalPageNum = getThreadNum(total, pageSize);	//总页数
			
			int start = (pageNumber - 1)*pageSize + 1;	//起始点
			int end = 0;								//结束点
			if (pageNumber == totalPageNum) {
				//访问最后一页(当前页码=总页数)
				end = total;
			} else {
				end = pageNumber*pageSize;
			}
			
			//获取分页的persons
			//System.out.println(start + " - " + end);
			for (int i = start; i <= end; i++) {
				pids_page.add(pids.get(i - 1));
			}
			
			//获取分页的person对象
			for (String string : pids_page) {
				list.add(personDao.findByDn(string));
			}
			
			return new PageImpl(list, request, total);
		} catch (Exception e) {
			wrapException(e);
		}
		return null;
	}

	/**
	 * 计算总页数
	 * @param total 数据总量
	 * @param commitSize	每页显示多少数据
	 * @return int
	 */
	public int getThreadNum(int total, int commitSize) {
		int num = total % commitSize;
		if (num == 0) {
			return total / commitSize;
		} else {
			return total / commitSize + 1;
		}
	}

	@Override
	public boolean addPositions(String organizationId, String departmentId,
			String positionIds) throws OrganizationException {
		return addUnit(organizationId, departmentId, positionIds,
				Constants.POSITION);
	}

	@Override
	public boolean removePositions(String organizationId, String departmentId,
			String positionIds) throws OrganizationException {
		return removeUnit(organizationId, departmentId, positionIds,
				Constants.POSITION);
	}

	@Override
	public List<Position> allPositions(String organizationId,
			String departmentId) throws OrganizationException {
		List<Position> list = new ArrayList<Position>();
		try {
			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);
			validateDepartment(deUnit.getDn().toString(), departmentId);

			List<String> pids = departmentDao.allPositions(departmentDao
					.findByPrimaryKey(deUnit.getDn().toString(), departmentId));

			for (String string : pids) {
				list.add(positionDao.findByDn(string));
			}
		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public boolean addGroups(String organizationId, String departmentId,
			String groupIds) throws OrganizationException {
		return addUnit(organizationId, departmentId, groupIds, Constants.GROUP);
	}

	@Override
	public boolean removeGroups(String organizationId, String departmentId,
			String groupIds) throws OrganizationException {
		return removeUnit(organizationId, departmentId, groupIds,
				Constants.GROUP);
	}

	@Override
	public List<Group> allGroups(String organizationId, String departmentId)
			throws OrganizationException {
		List<Group> list = new ArrayList<Group>();
		try {
			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);
			validateDepartment(deUnit.getDn().toString(), departmentId);

			List<String> pids = departmentDao.allGroups(departmentDao
					.findByPrimaryKey(deUnit.getDn().toString(), departmentId));

			for (String string : pids) {
				list.add(groupDao.findByDn(string));
			}
		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public boolean addRoles(String organizationId, String departmentId,
			String roleIds) throws OrganizationException {
		return addUnit(organizationId, departmentId, roleIds, Constants.ROLE);
	}

	@Override
	public boolean removeRoles(String organizationId, String departmentId,
			String roleIds) throws OrganizationException {
		return removeUnit(organizationId, departmentId, roleIds, Constants.ROLE);
	}

	@Override
	public List<Role> allRoles(String organizationId, String departmentId)
			throws OrganizationException {
		List<Role> list = new ArrayList<Role>();
		try {
			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId,
					Constants.DEPARTMENT);
			validateDepartment(deUnit.getDn().toString(), departmentId);

			List<String> pids = departmentDao.allRoles(departmentDao
					.findByPrimaryKey(deUnit.getDn().toString(), departmentId));

			for (String string : pids) {
				list.add(roleDao.findByDn(string));
			}
		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public List<Department> adapt(String xml) throws AdapterException {
		try {
			Departments bs = JaxbUtils.xml2Object(xml, Departments.class);
			return bs.getDepartment();

		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}
	}

	@Override
	public String unadapt(List<Department> list) throws AdapterException {
		try {
			Departments bs = new Departments();
			bs.addAll(list);

			return JaxbUtils.object2Xml(bs, Departments.class);
		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}
	}

	@Override
	public Department findByDn(String dn) {
		try {
			return departmentDao.findByDn(dn);

		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return null;
		}
	}

	@Override
	public boolean deleteByDn(String dn) throws OrganizationException {
		try {
			departmentDao.deleteByDn(dn);
			return true;
		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return false;
		}
	}

	@Override
	public Department findByBid(String baseDn, String bid) {
		try {
			return departmentDao.findByPrimaryKey(baseDn, bid);
		} catch (Exception e) {
			printException(e);
		}
		return null;
	}

	@Override
	public void removePersonsOther(String organizationId, String dids,
			String pids) {
		String[] didss = StringUtils.split(dids, ";");
		String[] pidss = StringUtils.split(pids, ";");

		if (didss == null || pidss == null)
			return;

		for (int i = 0; i < didss.length; i++) {
			String[] didss2 = StringUtils.split(didss[i], ",");
			if (didss2 != null) {
				for (String string : didss2) {

					removePersons(organizationId, string, pidss[i]);
				}
			}
		}
	}

	@Override
	public Department existByName(String name) {
		// TODO Auto-generated method stub
		try {
			List<Department> list = departmentDao.existName(name);
			if (list.size() > 0) {
				return list.get(0);
			}
		} catch (Exception e) {
			printException(e);
		}
		return null;
	}

	@Override
	public Department existByGradeCode(String gradeCode) {
		// TODO Auto-generated method stub
		try {
			List<Department> list = departmentDao.existGradeCode(gradeCode);
			if (list.size() > 0) {
				return list.get(0);
			}
		} catch (Exception e) {
			printException(e);
		}
		return null;
	}

	@Override
	public List<Department> findDepartmentByPerson(String organizationId, Person person) {
		// TODO Auto-generated method stub
		return findDepartments(organizationId, Constants.PERSONS, person.getDn().toString());
	}
	
}
